/*
* Copyright (c) Microsoft Corporation.  All Rights Reserved.
*
* Public Mock10 Exception class
*/
#pragma once
#include "Mock10.h"
#include "DetourFunction.h"

#include <exception>

#pragma push_macro("SEALED")
#undef SEALED

#if _MSC_VER >= 1400
# define SEALED sealed
#else
# define SEALED
#endif

namespace Mock10
{
    namespace Private
    {
        class MOCK10_API Throw SEALED
        {
        public:
            static void __declspec(noreturn) __stdcall MockException(const MockStatus& mockStatus);
            static void __declspec(noreturn) __stdcall MockException(HRESULT errorCode);
            static void __declspec(noreturn) __stdcall MockException(HRESULT errorCode, const wchar_t* pszMessage);

            // wchar_t native type export
            #if defined(MOCK10_FULL_BUILD)
            static void __declspec(noreturn) __stdcall MockException(HRESULT errorCode, const __wchar_t* pszMessage);
            #endif

        private:
            Throw();
            ~Throw();
        };
    }

    class MockException SEALED : public std::exception
    {
    friend class Mock10::Private::Throw;

    public:
        virtual ~MockException(){};

        // Returns the HRESULT that was passed into the Exception constructor
        HRESULT ErrorCode() const
        {
            return m_errorCode;
        }

    protected:
        MockException(HRESULT errorCode, const char* pszMessage)
        : std::exception(pszMessage)
        , m_errorCode(errorCode)
        {
        }

    private:
        MockException& operator=(const MockException&); // non-implemented assignment operator

        // Making 'operator new' private prevents heap allocation of Exception, and forces Exception instances
        // to be thrown by value.
        static void* operator new(size_t);

        // Making 'operator delete' private for consistency with 'operator new'.
        static void operator delete(void*){};

        HRESULT m_errorCode;
    };
} /* namespace Mock10 */

#pragma pop_macro("SEALED")
